package com.good.shopping.search.thread;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * 异步 - 初始化线程
 *  4种方式：
 *      1 Thread 实现 2 Runnable接口 3 实现 Callable接口 4 线程池
 *
 * @author shengren.yan
 * @create 2022-03-01
 */
@Slf4j
public class ThreadTest1 {

    /** 日志的线程 */
    private final static ThreadLocal<String> logsThread = new ThreadLocal<String>();

    public static void main(String[] args) throws Exception {

         // 第一种：
//         System.out.println("main......start.....");
//         Thread thread = new Thread01();
//         thread.start();
//         System.out.println("main......end.....");

         // 第二种
//         Runable01 runable01 = new Runable01();
//         new Thread(runable01).start();

        // 第三种
//         FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
//         new Thread(futureTask).start();
//         System.out.println(futureTask.get());

        /**
         *   第四种 - 线程池
         *   七大参数：
         *      核心线程数 ：创建好以后就准备就绪的线程数量
         *      最大线程数量：控制资源
         *      存活时间： 如果当前正在运行的线程数量大于core数量，只要线程空闲大于指定的时间，就会释放
         *      时间单位：
         *      阻塞队列：BlockingQueue
         *      线程创建的工厂：ThreadFactory
         *      拒绝策略： 如果队列满了，按照我们指定的拒绝策略
         *          new ThreadPoolExecutor.AbortPolicy() 丢弃任务并抛出RejectedExecutionException异常
         *          new ThreadPoolExecutor.DiscardPolicy()  丢弃任务，但是不抛出异常
         *          new ThreadPoolExecutor.DiscardOldestPolicy() 丢弃队列最前面的任务，然后重新提交被拒绝的任务
         *          new ThreadPoolExecutor.CallerRunsPolicy()    调用线程处理该任务
          */

        ExecutorService threadPool = new ThreadPoolExecutor(
                200,
                10,
                10L,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(10000),
                Executors.defaultThreadFactory(),    // 默认工厂
                new ThreadPoolExecutor.AbortPolicy()
        );

        // 使用
        try {
            log.info("开始======================================================!");
            List<String> companyCodes = new ArrayList<>();
            if (companyCodes != null) {
                for (String companyCode : companyCodes) {
                    threadPool.submit(() -> {
                        try {
                            // 具体的业务逻辑。。
                        } catch (Exception e) {
                            // 运行异常 - 记录日志
                            String fullException = getFullException(e);
                        } finally {
                            logsThread.remove();
                        }
                    });
                }
            }

        } catch (Exception ex) {
            // 运行异常 - 记录日志
        } finally {
            //关闭线程池
            threadPool.shutdown();
        }


        // 定时任务的线程池
        ExecutorService service = Executors.newScheduledThreadPool(2);

    }

    public static class Thread01 extends Thread {
        @Override
        public void run() {
            System.out.println("当前线程id：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }
    }


    public static class Runable01 implements Runnable {
        @Override
        public void run() {
            System.out.println("当前线程id：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }
    }


    public static class Callable01 implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程id：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }
    }

    // 案例 ：线程池
    private ThreadPoolExecutor buildThreadPoolExecutor(int mainUnitRunThreadCount) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(mainUnitRunThreadCount,
                mainUnitRunThreadCount,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(20),
                new NamedThreadFactory("OLManMonJobService"));
        return threadPoolExecutor;
    }

    /**
     * 获取完整的异常信息
     *
     * @param ex
     * @return
     */
    private static String getFullException(Exception ex) {
        if (ex != null) {
            StringWriter stringWriter = new StringWriter();
            PrintWriter printWriter = new PrintWriter(stringWriter);
            ex.printStackTrace(printWriter);
            try {
                stringWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return stringWriter.toString();
        }
        return null;
    }

}
